<?php
/**
 * Created by PhpStorm.
 * User: panchaozhi
 * Date: 2016/11/17
 * Time: 17:19
 */

namespace frontend\models;

use Yii;
use yii\base\Model;
use common\models\ArticleModel;
use yii\base\Exception;
use common\models\RelationTagsArt;
use yii\db\Query;

class Article extends Model
{
    /**
     * 这些是创建文章的时候需要用到的字段，下面的 $this->attributes 用的就是这些
     * @var
     */
    public $id;
    public $title;
    public $content;
    public $label_img;
    public $cat_id;
    public $tags;

    public $_lassError = "";

    /**
     * 定义文章创建和更新的场景 常量
     */
    const SCENARIOS_CREATE = 'create';
    const SCENARIOS_UPDATE = 'update';

    /**
     * 定义事件的常量
     */
    const EVENT_AFTER_CREATE = 'eventAfterCreate';
    const EVENT_AFTER_UPDATE = 'eventAfterUpdate';

    /**
     * 定义文章创建和更新的场景
     * {@inheritDoc}
     * @see \yii\base\Model::scenarios()
     */
    public function scenarios()
    {
        $scenarios = [
            self::SCENARIOS_CREATE => ['title', 'content', 'label_img', 'cat_id', 'tags'],
            self::SCENARIOS_UPDATE => ['title', 'content', 'label_img', 'cat_id', 'tags'],
        ];
        return array_merge(parent::scenarios(), $scenarios);
    }
    public function rules()
    {
        return [
            [['id', 'title', 'content', 'cat_id',], 'required'],
            [['id', 'cat_id'], 'integer'],
            ['title', 'string', 'min' => 4, 'max' => 50],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => '编号',
            'title' => '标题',
            'content' => '内容',
            'label_img' => '标签图',
            'tags' => '标签',
            'cat_id' => '分类',
        ];
    }
    
    /**
     * 文章创建的方法
     * @throws Exception
     */
    public function create()
    {
        //创建事务，是为了处理失败的时候，标签已经存入了数据库，
        //而文章的内容和其他等保存失败却并没有存入数据库 的情况
        $transaction = Yii::$app->db->beginTransaction();
        
        try {
            $model = new ArticleModel();
            $model->setAttributes($this->attributes);
            $model->summary = $this->_getSummary();
            $model->user_id = Yii::$app->user->identity->id;
            $model->user_name = Yii::$app->user->identity->username;
            $model->is_valid = ArticleModel::IS_VALID;
            $model->created_at = time();
            $model->updated_at = time();
            
            //保存创建的文章到数据库
            if (!$model->save())
                throw new Exception('文章创建失败');
            
            //将传送过来的id赋值给这个表的id， 'id' => $model->id;这句以便存入数据库的id字段
            $this->id = $model->id;
            
            //array_merge 合并一个或多个数组
            //如果输入的数组中有相同的字符串键名，则该键名后面的值将覆盖前一个值
            //把这个数据传给文章创建后要做的事件 _eventAfterCreate()
            $data = array_merge($this->getAttributes(), $model->getAttributes());
//             print_r($data);
            $this->_eventAfterCreate($data);
            
            $transaction->commit();
            return true;
        } catch (Exception $e) {
            
            //如果创建失败则进行回滚，并抛出错误的信息
            $transaction->rollBack();
            $this->_lassError = $e->getMessage();
            return false;
        }
    }

    /**
     * 获取文章详情页面
     * @param $id
     * @return array|null|\yii\db\ActiveRecord
     * @throws Exception
     */
    public function getViewById($id)
    {
        $result = ArticleModel::find()->with('relate.tag', 'extend', 'cat')->where(['id' => $id])->asArray()->one();
        if (!$result) {
            throw new Exception("文章不存在！");
        }
        
        //获取分类
        
        
       
        //对标签进行处理
        $result['tags'] = [];
        if (isset($result['relate']) && !empty($result['relate'])) {
            foreach ($result['relate'] as $list) {
                $result['tags'][] = $list['tag']['tag_name'];
            }
        }
        
        unset($result['relate']);
//         print_r($result);
        return $result;
        
    }

    /**
     * 获取文章列表的数据 并进行数据的格式化和分页
     * @param $cond
     * @param int $curPage
     * @param int $pageSize
     * @param array $orderBy
     * @return array
     */
    public static function getList($cond, $curPage = 1, $pageSize = 6, $orderBy = ['id' => SORT_DESC])
    {
        $model = new ArticleModel();
        
        $select = ['id', 'title', 'summary', 'label_img', 'cat_id', 'is_valid', 'created_at', 'updated_at', 'user_id', 'user_name'];
        
        $query = $model->find()
            ->select($select)
            ->where($cond)
            ->with('relate.tag', 'extend')
            ->orderBy($orderBy);

        //获取分页数据
        $res = $model->getPages($query, $curPage, $pageSize);
        //格式化数据
        $res['data'] = self::_formatList($res['data']);
        
        return $res;
    }

    /**
     * 格式化数据
     * @param $data
     * @return mixed
     */
    public static function _formatList($data)
    {        
        foreach ($data as &$list) {
            $list['tags'] = [];
            if (isset($list['relate']) && !empty($list['relate'])) {
                foreach ($list['relate'] as $lt) {
                    $list['tags'][] = $lt['tag']['tag_name'];
                }
            }            
            unset($list['relate']);
        }
        
        return $data;
    }

    /**
     * 获取文章摘要的方法
     * @param int $s
     * @param int $e
     * @param string $char
     * @return null|string 将 content 的内容进行截取 $s->$e 的长度，对文章的内容进行过滤，防止有非法字符
     */
    public function _getSummary($s = 0, $e = 90, $char="utf-8")
    {
        if (empty($this->content)) {
            return null;
        }
        
        return (mb_substr(str_replace('&nbsp;', '', strip_tags($this->content)), $s, $e, $char));
    }
    
    /**
     * 创建事件的操作
     * @param array $data
     */
    public function _eventAfterCreate($data)
    {
        //添加事件，也就是文章创建完成之后，将文章的标签添加到数据库，中的表Tags中去
        //我们用一个 _eventAddTag()方法进行处理这个操作
        $this->on(self::EVENT_AFTER_CREATE, [$this, '_eventAddTag'], $data);
        //触发事件
        $this->trigger(self::EVENT_AFTER_CREATE);
    }

    /**
     * 添加文章标签关联关系的操作
     * @param $event
     * @throws Exception
     */
    public function _eventAddTag($event)
    {
        //创建一个标签模型，获取到 $data 里面的 tags，也就是我们输入表单的标签
        //把我们输入表单的标签赋值给标签模型的 tags字段，然后进行数据库的保存
        //保存之后获取这个标签的id , return $ids;在表单TagForm里面实现, 保存到表 tags表中
        $tag = new TagForm();
        $tag->tags = $event->data['tags'];
        $tagids = $tag->saveTags();
        
        //删除原先的关联关系
        //把文章跟标签的关系先删掉，然后再进行重新保存，data['id']是保存文章后获取到的id
        RelationTagsArt::deleteAll(['art_id' => $event->data['id']]);
        
        //批量保存文章标签的关联关系，保存到relation_tag_post表中
        $rows = array();
        if (!empty($tagids)) {
            foreach ($tagids as $k => $id) {
                $rows[$k]['art_id'] = $this->id;
                $rows[$k]['tags_id'] = $id;
            }
            
            //批量插入关联的表
            $res = (new Query())->createCommand()
                ->batchInsert(RelationTagsArt::tableName(), ['art_id', 'tags_id'], $rows)
                ->execute();
            if (!$res)
                throw new Exception("关联关系保存失败！");
        }
    }
}